﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.ServiceModel.Activation;
using Microsoft.SharePoint.Administration;

namespace MS.InformationManagement.DocumentIDServiceApp
{
    [Guid("31F7307F-3A2D-467F-9A07-25CEAE0CCDD8")]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public sealed class DocumentIDService : SPIisWebService, IServiceAdministration
    {
        #region [Constructor]
        public DocumentIDService() : base() { }

        public DocumentIDService(SPFarm farm)
            : base(farm)
        {
            this.Name = "DocumentIDService";
        } 
        #endregion

        #region [Singleton]

        private static DocumentIDService _currentInstance = null;
        private static Object _currentInstanceSyncLock = new Object();

        public static DocumentIDService CurrentInstance {
            get {
                if (_currentInstance == null)
                {
                    lock (_currentInstanceSyncLock) {
                        if (_currentInstance == null) {
                            _currentInstance = SPFarm.Local.Services.GetValue<DocumentIDService>("DocumentIDService");
                        }
                    }
                }
                return _currentInstance;
            }
        }

        #endregion

        #region [IServiceAdministration Members]

        public SPServiceApplication CreateApplication(string name, Type serviceApplicationType, SPServiceProvisioningContext provisioningContext)
        {
            if (provisioningContext == null)
                throw new ArgumentNullException("provisioningContext");
            if (serviceApplicationType != typeof(DocumentIDServiceApplication))
                throw new NotSupportedException("Invalid Service Application type, expected DocumentIDService");

            DocumentIDServiceApplication application =
                this.Farm.GetObject(
                    name,
                    this.Id,
                    serviceApplicationType) as DocumentIDServiceApplication;

            if (application == null)
            {
                SPDatabaseParameters databaseParameters =
                    SPDatabaseParameters.CreateParameters(
                        name,
                        SPDatabaseParameterOptions.GenerateUniqueName);

                application = DocumentIDServiceApplication.Create(
                    name,
                    this,
                    provisioningContext.IisWebServiceApplicationPool,
                    databaseParameters);
            }

            return (application);
        }

        public DocumentIDServiceApplication CreateApplication(string name, bool checkIfExist, SPIisWebServiceApplicationPool applicationPool)
        {
            if (checkIfExist)
            {
                DocumentIDServiceApplication webApplicationByName = this.GetWebApplicationByName(name);
                if (webApplicationByName != null)
                {
                    return webApplicationByName;
                }
            }

            SPDatabaseParameters databaseParameters =
                SPDatabaseParameters.CreateParameters(name, SPDatabaseParameterOptions.GenerateUniqueName);

            DocumentIDServiceApplication application = DocumentIDServiceApplication.Create(
                name,
                this,
                applicationPool,
                databaseParameters);

            return (application);
        }

        public SPServiceApplicationProxy CreateProxy(string name, SPServiceApplication serviceApplication, SPServiceProvisioningContext provisioningContext)
        {
            if (serviceApplication == null)
                throw new ArgumentNullException("serviceApplication");

            if (serviceApplication.GetType() != typeof(DocumentIDServiceApplication))
                throw new NotSupportedException("Invalid SPServiceApplication type");

            DocumentIDServiceProxy serviceProxy = (DocumentIDServiceProxy)base.Farm.GetObject(
                string.Empty,
                base.Farm.Id,
                typeof(DocumentIDServiceProxy));
            if (serviceProxy == null)
            {
                serviceProxy = new DocumentIDServiceProxy(base.Farm);
                serviceProxy.Update(true);
            }

            DocumentIDServiceApplicationProxy applicationProxy =
                serviceProxy.ApplicationProxies.GetValue<DocumentIDServiceApplicationProxy>(name);
            if (applicationProxy == null)
            {
                applicationProxy = new DocumentIDServiceApplicationProxy(
                    name,
                    serviceProxy,
                    ((DocumentIDServiceApplication)serviceApplication).Uri);
            }

            return applicationProxy;
        }

        public SPPersistedTypeDescription GetApplicationTypeDescription(Type serviceApplicationType)
        {
            if (serviceApplicationType != typeof(DocumentIDServiceApplication))
                throw new NotSupportedException("Invalid Service Application type, expected DocumentIDService");

            return new SPPersistedTypeDescription("DocumentID Service Application", "Document ID bank service application for the Information Management custom documentID generator");
        }

        public Type[] GetApplicationTypes()
        {
            return (new Type[] { typeof(DocumentIDServiceApplication) });
        }

        public override SPAdministrationLink GetCreateApplicationLink(Type serviceApplicationType)
        {
            return new SPAdministrationLink("/_admin/DocumentIDService/DocumentIDServiceCreate.aspx");
        }

        #endregion

        #region [Internal code]

        internal DocumentIDServiceApplication GetWebApplicationByName(string applicationName)
        {
            return (base.Applications.GetValue<DocumentIDServiceApplication>(applicationName));
        }

        #endregion
    }
}
